home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2005 October / PCWOCT05.iso / Software / FromTheMag / XAMPP 1.4.14 / xampp-win32-1.4.14-installer.exe / xampp / php / pear / DB / mssql.php < prev    next >
PHP Script  |  2004-10-01  |  23KB  |  739 lines

  1. <?php
  2. /* vim: set expandtab tabstop=4 shiftwidth=4 foldmethod=marker: */
  3. // +----------------------------------------------------------------------+
  4. // | PHP Version 4                                                        |
  5. // +----------------------------------------------------------------------+
  6. // | Copyright (c) 1997-2004 The PHP Group                                |
  7. // +----------------------------------------------------------------------+
  8. // | This source file is subject to version 2.02 of the PHP license,      |
  9. // | that is bundled with this package in the file LICENSE, and is        |
  10. // | available at through the world-wide-web at                           |
  11. // | http://www.php.net/license/2_02.txt.                                 |
  12. // | If you did not receive a copy of the PHP license and are unable to   |
  13. // | obtain it through the world-wide-web, please send a note to          |
  14. // | license@php.net so we can mail you a copy immediately.               |
  15. // +----------------------------------------------------------------------+
  16. // | Author: Sterling Hughes <sterling@php.net>                           |
  17. // | Maintainer: Daniel Convissor <danielc@php.net>                       |
  18. // +----------------------------------------------------------------------+
  19. //
  20. // $Id: mssql.php,v 1.55 2004/08/20 17:10:53 danielc Exp $
  21.  
  22. require_once 'DB/common.php';
  23.  
  24. /**
  25.  * Database independent query interface definition for PHP's Microsoft SQL Server
  26.  * extension.
  27.  *
  28.  * @package  DB
  29.  * @version  $Id: mssql.php,v 1.55 2004/08/20 17:10:53 danielc Exp $
  30.  * @category Database
  31.  * @author   Sterling Hughes <sterling@php.net>
  32.  */
  33. class DB_mssql extends DB_common
  34. {
  35.     // {{{ properties
  36.  
  37.     var $connection;
  38.     var $phptype, $dbsyntax;
  39.     var $prepare_tokens = array();
  40.     var $prepare_types = array();
  41.     var $transaction_opcount = 0;
  42.     var $autocommit = true;
  43.     var $_db = null;
  44.  
  45.     // }}}
  46.     // {{{ constructor
  47.  
  48.     function DB_mssql()
  49.     {
  50.         $this->DB_common();
  51.         $this->phptype = 'mssql';
  52.         $this->dbsyntax = 'mssql';
  53.         $this->features = array(
  54.             'prepare' => false,
  55.             'pconnect' => true,
  56.             'transactions' => true,
  57.             'limit' => 'emulate'
  58.         );
  59.         // XXX Add here error codes ie: 'S100E' => DB_ERROR_SYNTAX
  60.         $this->errorcode_map = array(
  61.             170   => DB_ERROR_SYNTAX,
  62.             207   => DB_ERROR_NOSUCHFIELD,
  63.             208   => DB_ERROR_NOSUCHTABLE,
  64.             245   => DB_ERROR_INVALID_NUMBER,
  65.             515   => DB_ERROR_CONSTRAINT_NOT_NULL,
  66.             547   => DB_ERROR_CONSTRAINT,
  67.             2627  => DB_ERROR_CONSTRAINT,
  68.             2714  => DB_ERROR_ALREADY_EXISTS,
  69.             3701  => DB_ERROR_NOSUCHTABLE,
  70.             8134  => DB_ERROR_DIVZERO,
  71.         );
  72.     }
  73.  
  74.     // }}}
  75.     // {{{ connect()
  76.  
  77.     function connect($dsninfo, $persistent = false)
  78.     {
  79.         if (!DB::assertExtension('mssql') && !DB::assertExtension('sybase')
  80.             && !DB::assertExtension('sybase_ct'))
  81.         {
  82.             return $this->raiseError(DB_ERROR_EXTENSION_NOT_FOUND);
  83.         }
  84.         $this->dsn = $dsninfo;
  85.         $dbhost = $dsninfo['hostspec'] ? $dsninfo['hostspec'] : 'localhost';
  86.         $dbhost .= $dsninfo['port'] ? ',' . $dsninfo['port'] : '';
  87.  
  88.         $connect_function = $persistent ? 'mssql_pconnect' : 'mssql_connect';
  89.  
  90.         if ($dbhost && $dsninfo['username'] && $dsninfo['password']) {
  91.             $conn = @$connect_function($dbhost, $dsninfo['username'],
  92.                                        $dsninfo['password']);
  93.         } elseif ($dbhost && $dsninfo['username']) {
  94.             $conn = @$connect_function($dbhost, $dsninfo['username']);
  95.         } else {
  96.             $conn = @$connect_function($dbhost);
  97.         }
  98.         if (!$conn) {
  99.             return $this->raiseError(DB_ERROR_CONNECT_FAILED, null, null,
  100.                                          null, @mssql_get_last_message());
  101.         }
  102.         if ($dsninfo['database']) {
  103.             if (!@mssql_select_db($dsninfo['database'], $conn)) {
  104.                 return $this->raiseError(DB_ERROR_NODBSELECTED, null, null,
  105.                                          null, @mssql_get_last_message());
  106.             }
  107.             $this->_db = $dsninfo['database'];
  108.         }
  109.         $this->connection = $conn;
  110.         return DB_OK;
  111.     }
  112.  
  113.     // }}}
  114.     // {{{ disconnect()
  115.  
  116.     function disconnect()
  117.     {
  118.         $ret = @mssql_close($this->connection);
  119.         $this->connection = null;
  120.         return $ret;
  121.     }
  122.  
  123.     // }}}
  124.     // {{{ simpleQuery()
  125.  
  126.     function simpleQuery($query)
  127.     {
  128.         $ismanip = DB::isManip($query);
  129.         $this->last_query = $query;
  130.         if (!@mssql_select_db($this->_db, $this->connection)) {
  131.             return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
  132.         }
  133.         $query = $this->modifyQuery($query);
  134.         if (!$this->autocommit && $ismanip) {
  135.             if ($this->transaction_opcount == 0) {
  136.                 $result = @mssql_query('BEGIN TRAN', $this->connection);
  137.                 if (!$result) {
  138.                     return $this->mssqlRaiseError();
  139.                 }
  140.             }
  141.             $this->transaction_opcount++;
  142.         }
  143.         $result = @mssql_query($query, $this->connection);
  144.         if (!$result) {
  145.             return $this->mssqlRaiseError();
  146.         }
  147.         // Determine which queries that should return data, and which
  148.         // should return an error code only.
  149.         return $ismanip ? DB_OK : $result;
  150.     }
  151.  
  152.     // }}}
  153.     // {{{ nextResult()
  154.  
  155.     /**
  156.      * Move the internal mssql result pointer to the next available result
  157.      *
  158.      * @param a valid fbsql result resource
  159.      *
  160.      * @access public
  161.      *
  162.      * @return true if a result is available otherwise return false
  163.      */
  164.     function nextResult($result)
  165.     {
  166.         return @mssql_next_result($result);
  167.     }
  168.  
  169.     // }}}
  170.     // {{{ fetchInto()
  171.  
  172.     /**
  173.      * Fetch a row and insert the data into an existing array.
  174.      *
  175.      * Formating of the array and the data therein are configurable.
  176.      * See DB_result::fetchInto() for more information.
  177.      *
  178.      * @param resource $result    query result identifier
  179.      * @param array    $arr       (reference) array where data from the row
  180.      *                            should be placed
  181.      * @param int      $fetchmode how the resulting array should be indexed
  182.      * @param int      $rownum    the row number to fetch
  183.      *
  184.      * @return mixed DB_OK on success, null when end of result set is
  185.      *               reached or on failure
  186.      *
  187.      * @see DB_result::fetchInto()
  188.      * @access private
  189.      */
  190.     function fetchInto($result, &$arr, $fetchmode, $rownum=null)
  191.     {
  192.         if ($rownum !== null) {
  193.             if (!@mssql_data_seek($result, $rownum)) {
  194.                 return null;
  195.             }
  196.         }
  197.         if ($fetchmode & DB_FETCHMODE_ASSOC) {
  198.             $arr = @mssql_fetch_array($result, MSSQL_ASSOC);
  199.             if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE && $arr) {
  200.                 $arr = array_change_key_case($arr, CASE_LOWER);
  201.             }
  202.         } else {
  203.             $arr = @mssql_fetch_row($result);
  204.         }
  205.         if (!$arr) {
  206.             /* This throws informative error messages,
  207.                don't use it for now
  208.             if ($msg = @mssql_get_last_message()) {
  209.                 return $this->raiseError($msg);
  210.             }
  211.             */
  212.             return null;
  213.         }
  214.         if ($this->options['portability'] & DB_PORTABILITY_RTRIM) {
  215.             $this->_rtrimArrayValues($arr);
  216.         }
  217.         if ($this->options['portability'] & DB_PORTABILITY_NULL_TO_EMPTY) {
  218.             $this->_convertNullArrayValuesToEmpty($arr);
  219.         }
  220.         return DB_OK;
  221.     }
  222.  
  223.     // }}}
  224.     // {{{ freeResult()
  225.  
  226.     function freeResult($result)
  227.     {
  228.         return @mssql_free_result($result);
  229.     }
  230.  
  231.     // }}}
  232.     // {{{ numCols()
  233.  
  234.     function numCols($result)
  235.     {
  236.         $cols = @mssql_num_fields($result);
  237.         if (!$cols) {
  238.             return $this->mssqlRaiseError();
  239.         }
  240.         return $cols;
  241.     }
  242.  
  243.     // }}}
  244.     // {{{ numRows()
  245.  
  246.     function numRows($result)
  247.     {
  248.         $rows = @mssql_num_rows($result);
  249.         if ($rows === false) {
  250.             return $this->mssqlRaiseError();
  251.         }
  252.         return $rows;
  253.     }
  254.  
  255.     // }}}
  256.     // {{{ autoCommit()
  257.  
  258.     /**
  259.      * Enable/disable automatic commits
  260.      */
  261.     function autoCommit($onoff = false)
  262.     {
  263.         // XXX if $this->transaction_opcount > 0, we should probably
  264.         // issue a warning here.
  265.         $this->autocommit = $onoff ? true : false;
  266.         return DB_OK;
  267.     }
  268.  
  269.     // }}}
  270.     // {{{ commit()
  271.  
  272.     /**
  273.      * Commit the current transaction.
  274.      */
  275.     function commit()
  276.     {
  277.         if ($this->transaction_opcount > 0) {
  278.             if (!@mssql_select_db($this->_db, $this->connection)) {
  279.                 return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
  280.             }
  281.             $result = @mssql_query('COMMIT TRAN', $this->connection);
  282.             $this->transaction_opcount = 0;
  283.             if (!$result) {
  284.                 return $this->mssqlRaiseError();
  285.             }
  286.         }
  287.         return DB_OK;
  288.     }
  289.  
  290.     // }}}
  291.     // {{{ rollback()
  292.  
  293.     /**
  294.      * Roll back (undo) the current transaction.
  295.      */
  296.     function rollback()
  297.     {
  298.         if ($this->transaction_opcount > 0) {
  299.             if (!@mssql_select_db($this->_db, $this->connection)) {
  300.                 return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
  301.             }
  302.             $result = @mssql_query('ROLLBACK TRAN', $this->connection);
  303.             $this->transaction_opcount = 0;
  304.             if (!$result) {
  305.                 return $this->mssqlRaiseError();
  306.             }
  307.         }
  308.         return DB_OK;
  309.     }
  310.  
  311.     // }}}
  312.     // {{{ affectedRows()
  313.  
  314.     /**
  315.      * Gets the number of rows affected by the last query.
  316.      * if the last query was a select, returns 0.
  317.      *
  318.      * @return number of rows affected by the last query or DB_ERROR
  319.      */
  320.     function affectedRows()
  321.     {
  322.         if (DB::isManip($this->last_query)) {
  323.             $res = @mssql_query('select @@rowcount', $this->connection);
  324.             if (!$res) {
  325.                 return $this->mssqlRaiseError();
  326.             }
  327.             $ar = @mssql_fetch_row($res);
  328.             if (!$ar) {
  329.                 $result = 0;
  330.             } else {
  331.                 @mssql_free_result($res);
  332.                 $result = $ar[0];
  333.             }
  334.         } else {
  335.             $result = 0;
  336.         }
  337.         return $result;
  338.     }
  339.  
  340.     // }}}
  341.     // {{{ nextId()
  342.  
  343.     /**
  344.      * Returns the next free id in a sequence
  345.      *
  346.      * @param string  $seq_name  name of the sequence
  347.      * @param boolean $ondemand  when true, the seqence is automatically
  348.      *                           created if it does not exist
  349.      *
  350.      * @return int  the next id number in the sequence.  DB_Error if problem.
  351.      *
  352.      * @internal
  353.      * @see DB_common::nextID()
  354.      * @access public
  355.      */
  356.     function nextId($seq_name, $ondemand = true)
  357.     {
  358.         $seqname = $this->getSequenceName($seq_name);
  359.         if (!@mssql_select_db($this->_db, $this->connection)) {
  360.             return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
  361.         }
  362.         $repeat = 0;
  363.         do {
  364.             $this->pushErrorHandling(PEAR_ERROR_RETURN);
  365.             $result = $this->query("INSERT INTO $seqname (vapor) VALUES (0)");
  366.             $this->popErrorHandling();
  367.             if ($ondemand && DB::isError($result) &&
  368.                 ($result->getCode() == DB_ERROR || $result->getCode() == DB_ERROR_NOSUCHTABLE))
  369.             {
  370.                 $repeat = 1;
  371.                 $result = $this->createSequence($seq_name);
  372.                 if (DB::isError($result)) {
  373.                     return $this->raiseError($result);
  374.                 }
  375.             } elseif (!DB::isError($result)) {
  376.                 $result =& $this->query("SELECT @@IDENTITY FROM $seqname");
  377.                 $repeat = 0;
  378.             } else {
  379.                 $repeat = false;
  380.             }
  381.         } while ($repeat);
  382.         if (DB::isError($result)) {
  383.             return $this->raiseError($result);
  384.         }
  385.         $result = $result->fetchRow(DB_FETCHMODE_ORDERED);
  386.         return $result[0];
  387.     }
  388.  
  389.     /**
  390.      * Creates a new sequence
  391.      *
  392.      * @param string $seq_name  name of the new sequence
  393.      *
  394.      * @return int  DB_OK on success.  A DB_Error object is returned if
  395.      *              problems arise.
  396.      *
  397.      * @internal
  398.      * @see DB_common::createSequence()
  399.      * @access public
  400.      */
  401.     function createSequence($seq_name)
  402.     {
  403.         $seqname = $this->getSequenceName($seq_name);
  404.         return $this->query("CREATE TABLE $seqname ".
  405.                             '([id] [int] IDENTITY (1, 1) NOT NULL ,' .
  406.                             '[vapor] [int] NULL)');
  407.     }
  408.  
  409.     // }}}
  410.     // {{{ dropSequence()
  411.  
  412.     /**
  413.      * Deletes a sequence
  414.      *
  415.      * @param string $seq_name  name of the sequence to be deleted
  416.      *
  417.      * @return int  DB_OK on success.  DB_Error if problems.
  418.      *
  419.      * @internal
  420.      * @see DB_common::dropSequence()
  421.      * @access public
  422.      */
  423.     function dropSequence($seq_name)
  424.     {
  425.         $seqname = $this->getSequenceName($seq_name);
  426.         return $this->query("DROP TABLE $seqname");
  427.     }
  428.  
  429.     // }}}
  430.     // {{{ errorNative()
  431.  
  432.     /**
  433.      * Determine MS SQL Server error code by querying @@ERROR.
  434.      *
  435.      * @return mixed  mssql's native error code or DB_ERROR if unknown.
  436.      */
  437.     function errorNative()
  438.     {
  439.         $res = @mssql_query('select @@ERROR as ErrorCode', $this->connection);
  440.         if (!$res) {
  441.             return DB_ERROR;
  442.         }
  443.         $row = @mssql_fetch_row($res);
  444.         return $row[0];
  445.     }
  446.  
  447.     // }}}
  448.     // {{{ errorCode()
  449.  
  450.     /**
  451.      * Determine PEAR::DB error code from mssql's native codes.
  452.      *
  453.      * If <var>$nativecode</var> isn't known yet, it will be looked up.
  454.      *
  455.      * @param  mixed  $nativecode  mssql error code, if known
  456.      * @return integer  an error number from a DB error constant
  457.      * @see errorNative()
  458.      */
  459.     function errorCode($nativecode = null)
  460.     {
  461.         if (!$nativecode) {
  462.             $nativecode = $this->errorNative();
  463.         }
  464.         if (isset($this->errorcode_map[$nativecode])) {
  465.             return $this->errorcode_map[$nativecode];
  466.         } else {
  467.             return DB_ERROR;
  468.         }
  469.     }
  470.  
  471.     // }}}
  472.     // {{{ mssqlRaiseError()
  473.  
  474.     /**
  475.      * Gather information about an error, then use that info to create a
  476.      * DB error object and finally return that object.
  477.      *
  478.      * @param  integer  $code  PEAR error number (usually a DB constant) if
  479.      *                         manually raising an error
  480.      * @return object  DB error object
  481.      * @see errorCode()
  482.      * @see errorNative()
  483.      * @see DB_common::raiseError()
  484.      */
  485.     function mssqlRaiseError($code = null)
  486.     {
  487.         $message = @mssql_get_last_message();
  488.         if (!$code) {
  489.             $code = $this->errorNative();
  490.         }
  491.         return $this->raiseError($this->errorCode($code), null, null, null,
  492.                                  "$code - $message");
  493.     }
  494.  
  495.     // }}}
  496.     // {{{ tableInfo()
  497.  
  498.     /**
  499.      * Returns information about a table or a result set.
  500.      *
  501.      * NOTE: only supports 'table' and 'flags' if <var>$result</var>
  502.      * is a table name.
  503.      *
  504.      * @param object|string  $result  DB_result object from a query or a
  505.      *                                string containing the name of a table
  506.      * @param int            $mode    a valid tableInfo mode
  507.      * @return array  an associative array with the information requested
  508.      *                or an error object if something is wrong
  509.      * @access public
  510.      * @internal
  511.      * @see DB_common::tableInfo()
  512.      */
  513.     function tableInfo($result, $mode = null)
  514.     {
  515.         if (isset($result->result)) {
  516.             /*
  517.              * Probably received a result object.
  518.              * Extract the result resource identifier.
  519.              */
  520.             $id = $result->result;
  521.             $got_string = false;
  522.         } elseif (is_string($result)) {
  523.             /*
  524.              * Probably received a table name.
  525.              * Create a result resource identifier.
  526.              */
  527.             if (!@mssql_select_db($this->_db, $this->connection)) {
  528.                 return $this->mssqlRaiseError(DB_ERROR_NODBSELECTED);
  529.             }
  530.             $id = @mssql_query("SELECT * FROM $result WHERE 1=0",
  531.                                $this->connection);
  532.             $got_string = true;
  533.         } else {
  534.             /*
  535.              * Probably received a result resource identifier.
  536.              * Copy it.
  537.              * Deprecated.  Here for compatibility only.
  538.              */
  539.             $id = $result;
  540.             $got_string = false;
  541.         }
  542.  
  543.         if (!is_resource($id)) {
  544.             return $this->mssqlRaiseError(DB_ERROR_NEED_MORE_DATA);
  545.         }
  546.  
  547.         if ($this->options['portability'] & DB_PORTABILITY_LOWERCASE) {
  548.             $case_func = 'strtolower';
  549.         } else {
  550.             $case_func = 'strval';
  551.         }
  552.  
  553.         $count = @mssql_num_fields($id);
  554.  
  555.         // made this IF due to performance (one if is faster than $count if's)
  556.         if (!$mode) {
  557.             for ($i=0; $i<$count; $i++) {
  558.                 $res[$i]['table'] = $got_string ? $case_func($result) : '';
  559.                 $res[$i]['name']  = $case_func(@mssql_field_name($id, $i));
  560.                 $res[$i]['type']  = @mssql_field_type($id, $i);
  561.                 $res[$i]['len']   = @mssql_field_length($id, $i);
  562.                 // We only support flags for tables
  563.                 $res[$i]['flags'] = $got_string ? $this->_mssql_field_flags($result, $res[$i]['name']) : '';
  564.             }
  565.  
  566.         } else { // full
  567.             $res['num_fields']= $count;
  568.  
  569.             for ($i=0; $i<$count; $i++) {
  570.                 $res[$i]['table'] = $got_string ? $case_func($result) : '';
  571.                 $res[$i]['name']  = $case_func(@mssql_field_name($id, $i));
  572.                 $res[$i]['type']  = @mssql_field_type($id, $i);
  573.                 $res[$i]['len']   = @mssql_field_length($id, $i);
  574.                 // We only support flags for tables
  575.                 $res[$i]['flags'] = $got_string ? $this->_mssql_field_flags($result, $res[$i]['name']) : '';
  576.  
  577.                 if ($mode & DB_TABLEINFO_ORDER) {
  578.                     $res['order'][$res[$i]['name']] = $i;
  579.                 }
  580.                 if ($mode & DB_TABLEINFO_ORDERTABLE) {
  581.                     $res['ordertable'][$res[$i]['table']][$res[$i]['name']] = $i;
  582.                 }
  583.             }
  584.         }
  585.  
  586.         // free the result only if we were called on a table
  587.         if ($got_string) {
  588.             @mssql_free_result($id);
  589.         }
  590.         return $res;
  591.     }
  592.  
  593.     // }}}
  594.     // {{{ getSpecialQuery()
  595.  
  596.     /**
  597.      * Returns the query needed to get some backend info
  598.      * @param string $type What kind of info you want to retrieve
  599.      * @return string The SQL query string
  600.      */
  601.     function getSpecialQuery($type)
  602.     {
  603.         switch ($type) {
  604.             case 'tables':
  605.                 return "select name from sysobjects where type = 'U' order by name";
  606.             case 'views':
  607.                 return "select name from sysobjects where type = 'V'";
  608.             default:
  609.                 return null;
  610.         }
  611.     }
  612.  
  613.     // }}}
  614.     // {{{ _mssql_field_flags()
  615.  
  616.     /**
  617.      * Get the flags for a field, currently supports "not_null", "primary_key",
  618.      * "auto_increment" (mssql identity), "timestamp" (mssql timestamp),
  619.      * "unique_key" (mssql unique index, unique check or primary_key) and
  620.      * "multiple_key" (multikey index)
  621.      *
  622.      * mssql timestamp is NOT similar to the mysql timestamp so this is maybe
  623.      * not useful at all - is the behaviour of mysql_field_flags that primary
  624.      * keys are alway unique? is the interpretation of multiple_key correct?
  625.      *
  626.      * @param string The table name
  627.      * @param string The field
  628.      * @author Joern Barthel <j_barthel@web.de>
  629.      * @access private
  630.      */
  631.     function _mssql_field_flags($table, $column)
  632.     {
  633.         static $tableName = null;
  634.         static $flags = array();
  635.  
  636.         if ($table != $tableName) {
  637.  
  638.             $flags = array();
  639.             $tableName = $table;
  640.  
  641.             // get unique and primary keys
  642.             $res = $this->getAll("EXEC SP_HELPINDEX[$table]", DB_FETCHMODE_ASSOC);
  643.  
  644.             foreach ($res as $val) {
  645.                 $keys = explode(', ', $val['index_keys']);
  646.  
  647.                 if (sizeof($keys) > 1) {
  648.                     foreach ($keys as $key) {
  649.                         $this->_add_flag($flags[$key], 'multiple_key');
  650.                     }
  651.                 }
  652.  
  653.                 if (strpos($val['index_description'], 'primary key')) {
  654.                     foreach ($keys as $key) {
  655.                         $this->_add_flag($flags[$key], 'primary_key');
  656.                     }
  657.                 } elseif (strpos($val['index_description'], 'unique')) {
  658.                     foreach ($keys as $key) {
  659.                         $this->_add_flag($flags[$key], 'unique_key');
  660.                     }
  661.                 }
  662.             }
  663.  
  664.             // get auto_increment, not_null and timestamp
  665.             $res = $this->getAll("EXEC SP_COLUMNS[$table]", DB_FETCHMODE_ASSOC);
  666.  
  667.             foreach ($res as $val) {
  668.                 $val = array_change_key_case($val, CASE_LOWER);
  669.                 if ($val['nullable'] == '0') {
  670.                     $this->_add_flag($flags[$val['column_name']], 'not_null');
  671.                 }
  672.                 if (strpos($val['type_name'], 'identity')) {
  673.                     $this->_add_flag($flags[$val['column_name']], 'auto_increment');
  674.                 }
  675.                 if (strpos($val['type_name'], 'timestamp')) {
  676.                     $this->_add_flag($flags[$val['column_name']], 'timestamp');
  677.                 }
  678.             }
  679.         }
  680.  
  681.         if (array_key_exists($column, $flags)) {
  682.             return(implode(' ', $flags[$column]));
  683.         }
  684.         return '';
  685.     }
  686.  
  687.     // }}}
  688.     // {{{ _add_flag()
  689.  
  690.     /**
  691.      * Adds a string to the flags array if the flag is not yet in there
  692.      * - if there is no flag present the array is created.
  693.      *
  694.      * @param reference  Reference to the flag-array
  695.      * @param value      The flag value
  696.      * @access private
  697.      * @author Joern Barthel <j_barthel@web.de>
  698.      */
  699.     function _add_flag(&$array, $value)
  700.     {
  701.         if (!is_array($array)) {
  702.             $array = array($value);
  703.         } elseif (!in_array($value, $array)) {
  704.             array_push($array, $value);
  705.         }
  706.     }
  707.  
  708.     // }}}
  709.     // {{{ quoteIdentifier()
  710.  
  711.     /**
  712.      * Quote a string so it can be safely used as a table / column name
  713.      *
  714.      * Quoting style depends on which database driver is being used.
  715.      *
  716.      * @param string $str  identifier name to be quoted
  717.      *
  718.      * @return string  quoted identifier string
  719.      *
  720.      * @since 1.6.0
  721.      * @access public
  722.      */
  723.     function quoteIdentifier($str)
  724.     {
  725.         return '[' . str_replace(']', ']]', $str) . ']';
  726.     }
  727.  
  728.     // }}}
  729. }
  730.  
  731. /*
  732.  * Local variables:
  733.  * tab-width: 4
  734.  * c-basic-offset: 4
  735.  * End:
  736.  */
  737.  
  738. ?>
  739.